/*
 * Node.cpp
 *
 *  Created on: 2009-9-26
 *      Author: ws
 */
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>


#include"Node.hpp"

#include"Value.hpp"

#include"Dep.hpp"


/*
 * ==================================================================
 * 	friend global function for VIter
 * =============================================================
 */

bool operator != (const Node::DVIter & x, const Node::DVIter &y)
{
	 if((x.i == y.i) && (x.n == y.n))
		 return false;
			 else
		return true;
}

bool operator == (const Node::DVIter &x, const Node::DVIter &y)
{
	if(x.i == y.i && x.n == y.n)
		return true;
	else
		return false;
}

bool operator != (const Node::UVIter & x, const Node::UVIter &y)
{
	 if((x.i == y.i) && (x.n == y.n))
		 return false;
			 else
		return true;
}

bool operator == (const Node::UVIter &x, const Node::UVIter &y)
{
	if(x.i == y.i && x.n == y.n)
		return true;
	else
		return false;
}




void Node::print()const
{

}

void Node::init_uses()
{
	for(int i = 0; i < operands[SRC].size(); i++)
	{
		if(operands[SRC][i]->isa(REG_VT))
		{
			regs[USE].push_back(location(SRC, i));
		}
	}
	for(int i = 0; i < operands[IMPLICT_SRC].size(); i++)
	{
		if(operands[IMPLICT_SRC][i]->isa(REG_VT))
		{
			regs[USE].push_back(location(IMPLICT_SRC, i));
		}
	}
}

void Node::init_defs()
{
	for(int i = 0; i < operands[DEST].size(); i++)
	{
		if(operands[DEST][i]->isa( REG_VT))
		{
			regs[DEF].push_back(location(DEST, i));
		}
	}
	for(int i = 0; i < operands[IMPLICT_DEST].size(); i++)
	{
		if(operands[IMPLICT_DEST][i]->isa(REG_VT))
		{
			regs[DEF].push_back(location(IMPLICT_DEST, i));
		}
	}
}

Node::DVIter Node::diter_begin()
{
	return DVIter(this, 0);
}

Node::DVIter Node::diter_end()
{
	return DVIter(this, regs[DEF].size());
}

Node::UVIter Node::uiter_begin()
{
	return UVIter(this, regs[USE].size());
}

Node::UVIter Node::uiter_end()
{
	return UVIter(this, regs[USE].size());
}

ODIter Node::OUT_Dbegin(unsigned int flag)const
{
	return outdeps.begin(flag);
}

IDIter Node::IN_Dbegin(unsigned int flag)const
{
	return indeps.begin(flag);
}


bool Node::all_outdep_is_visited(unsigned int flag)const
{
	for(ODIter it = OUT_Dbegin(flag); !it.is_end(); it++)
	{
		if(! (it)->is_visited() )
			return false;
	}
	return true;
}

bool Node::all_indep_is_visited(unsigned int flag)const
{
	for(IDIter it = IN_Dbegin(flag); !it.is_end(); it++)
	{
		if(!(it)->is_visited())
			return false;
	}
	return true;
}

bool Node::all_outdep_is_visited(unsigned int flag, location& loc)const
{
	for(ODIter it = OUT_Dbegin(flag); !it.is_end(); it++)
	{
		if(loc != (it)->get_from_loc())
			continue;
		if(! (it)->get_to_node()->is_visited())
			return false;
	}
	return true;
}

Dep_Sequence<Dep::OUTD>& Node::get_outdep()
{
	return outdeps;
}

Dep_Sequence<Dep::IND>& Node::get_indep()
{
	return indeps;
}

void Node::add_indep(Dep * d)
{
	indeps.add(d);
}
void Node::add_outdep(Dep * d)
{
	outdeps.add(d);
}

void Node::set_visited()
{
	visited = true;
}

void Node::reset_visited()
{
	visited = false;
}


bool Node::is_visited()
{
	return visited;
}



void Node::update_depth(int depth, unsigned int flag)
{
	if(get_depth() > depth)
		assert("update_depth(...): error  the depth  "==  "  not invalidate");
	set_depth(depth);
	for(ODIter it = OUT_Dbegin(flag); !it.is_end(); it++)
	{
		(it)->get_to_node()->set_depth(depth + (it)->get_weight());
	}
}
/*
 * just assign the data value, for the load ,store
 * only the data operand is assigned  cluster;
 */
void Node::assign_cluster(enum LOC_Type t, enum Core c)
{
	for(int i = 0; i < operands[t].size(); i++)
	{
		GenValue * gen = GenValue_cast(operands[t][i]);
		assert(gen != NULL);
		gen->set_cluster(c);
	}
}

void Node::sort_indeps()
{
	assert("error" == "TODO");
}

void Node::print_outdeps()
{

}

void Node::print_indeps()
{
}

std::vector<Dep *> Node::get_value_indep(Value * v , unsigned int flag)
{
	std::vector<Dep *> ret;
	for(IDIter dit = indeps.begin(flag);  !dit.is_end(); dit++)
	{
		if((dit)->get_to_value() == v && dit->get_type_flag() & flag)
		{
			ret.push_back( dit.operator ->());
		}
	}
	return ret;
}

std::vector<Dep *>  Node::get_value_outdep(Value * v, unsigned int flag)
{
	std::vector<Dep*> ret;
	for(ODIter dit = outdeps.begin(flag); !dit.is_end(); dit++)
	{
		if((dit)->get_from_value() == v && dit->get_type_flag() & flag)
		{
			ret.push_back(dit.operator ->());
		}
	}
	return ret;
}

//special for Node
std::string Node::get_type_name()const
{
	switch(get_type_flag())
	{
	case SIMD_MATH:
		return "SIMD_MATH";
	case SIMD_LOAD:
		return "SIMD_LOAD";
	case SIMD_STORE:
		return "SIMD_STORE";
	case LOAD:
		return "LOAD";
	case STORE:
		return "STORE";
	case ADDR_OPER:
		return "ADDR_OPER";
	case DATA_ADDR:
		return "DATA_ADDR";
	case ADDR_DATA:
		return "ADDR_DATA";
	case NORMAL_OPER:
		return "NORMAL_OPER";
	case JSR:
		return "JSR";
	case JSR_SR:
		return "JSR_SR";
	case RTS:
		return "RTS";
	case BR_OPER:
		return "BR_OPER";
	case START_NODE:
		return "START_NODE";
	case END_NODE:
		return "END_NODE";
	default:
		assert("node::get_type_name():  type" == " unexpected type");
	}
}

void Node::src_assign_physical_register(int id, enum TargetInfo::PhysicalRegister physical_register )
{
	for(UVIter uv = uiter_begin(); uv != uiter_end(); uv++)
	{
		if(uv->get_id() == id)
		{
			uv->assign_physical_register(physical_register);
		}
	}
}

void Node::dest_assign_physical_register(int id, enum TargetInfo::PhysicalRegister physical_register )
{
	for(DVIter dv = diter_begin(); dv != diter_end(); dv++)
	{
		if(dv->get_id() == id)
		{
			dv->assign_physical_register(physical_register);
		}
	}	
}

